/**
 * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.babble.subitem.service.impl;

import cn.hutool.core.util.ArrayUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.babble.subitem.conversion.TagConversion;
import com.babble.subitem.dto.TagSaveDTO;
import com.babble.subitem.dto.TagUpdDTO;
import com.babble.subitem.entity.Tag;
import com.babble.subitem.mapper.TagMapper;
import com.babble.subitem.service.ITagService;
import com.babble.subitem.vo.TagVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springblade.common.cache.CacheNames;
import org.springblade.common.enums.CodeMsg;
import org.springblade.common.exception.MsgException;
import org.springblade.core.secure.utils.SecureUtil;
import org.springblade.core.tool.utils.RedisUtil;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 标签表 服务实现类
 *
 * @author Blade
 * @since 2021-11-21
 */
@RequiredArgsConstructor
@Service
public class TagServiceImpl extends ServiceImpl<TagMapper, Tag> implements ITagService {
	private final TagConversion tagConversion;
	private final TagMapper mapper;
	private final RedisUtil redisUtil;
	@Override
	public IPage<TagVO> selectTagPage(IPage<TagVO> page, TagVO tag) {
		return page.setRecords(baseMapper.selectTagPage(page, tag));
	}
	@Override
	public List<Tag> selectTags() {
		Object json = redisUtil.get(CacheNames.HOME_PAGE_TAGS);
		if(json==null){
			List<Tag> list = this.list(new QueryWrapper<Tag>().orderByAsc("click_count").orderByAsc("update_time"));
			redisUtil.set(CacheNames.HOME_PAGE_TAGS, JSON.toJSON(list));
			return list;
		}
			List<Tag> tags = JSONArray.parseArray(json.toString(), Tag.class);
			return tags;
	}
	@Override
	public void clickTag(String id) throws MsgException {
		List<Tag> tag = getTagIsId(id);
		if(tag==null || tag.size()==0){
			throw new MsgException(CodeMsg.TAG_EXISTS_ERROR.getCode(),CodeMsg.TAG_EXISTS_ERROR.getMsg());
		}
		Tag entity = tag.get(0);
		Long userId = SecureUtil.getUser().getUserId();
		Object json = redisUtil.get(CacheNames.HOME_CLICK_TAGS+userId+":"+id);
		if(json==null){
			entity.setClickCount(entity.getClickCount()+1);
			this.updateById(entity);
			redisUtil.set(CacheNames.HOME_CLICK_TAGS+userId+":"+id,"0",60, TimeUnit.SECONDS);
			addClickTag(entity.getId());
			return;
		}
		throw new MsgException(CodeMsg.TAG_CLICK_EXISTS_ERROR.getCode(),CodeMsg.TAG_CLICK_EXISTS_ERROR.getMsg());
	}


	@Override
	public List<Tag> info(String id) throws MsgException {
		String[] ids = id.split(",");
		if(ids.length>=1){
			List<Tag> info = selectTags().stream().filter(item->{
				if(ArrayUtil.contains(ids,item.getId())){
					return true;
				}
				return false;
			}).collect(Collectors.toList());
			if(info.size()!=ids.length){
				throw new MsgException(CodeMsg.TAG_EXISTS_ERROR.getCode(),CodeMsg.TAG_EXISTS_ERROR.getMsg());
			}
			return info;
		}
			List<Tag> tag = getTagIsId(id);
			if(tag==null || tag.size()==0){
				throw new MsgException(CodeMsg.TAG_EXISTS_ERROR.getCode(),CodeMsg.TAG_EXISTS_ERROR.getMsg());
			}

		return tag;
	}

	@Override
	public void saveToTag(TagSaveDTO entity) throws MsgException {
		Tag tag = tagConversion.TagSaveVOToTag(entity);
		String tagName = tag.getContent();
		//根据名字获取博客分类集合
		List<Tag> tags = getTagIsName(tagName);
		if(tags!=null && tags.size()!=0){
			throw new MsgException(CodeMsg.TAG_EXISTS_CREATE_ERROR.getCode(),CodeMsg.TAG_EXISTS_CREATE_ERROR.getMsg());
		}
		//添加数据库和redis
		tag.setCreateTime(LocalDateTime.now());
		tag.setUpdateTime(LocalDateTime.now());
		this.save(tag);
		//刷新redis中的数据
		Tag byId = this.getById(tag.getId());
		addTag(byId);
	}

	@Override
	public void delToTag(String id) {
		//TODO (cyq) 删除后,(是否博客文章跟着删除)
	}

	@Override
	public void updToTag(TagUpdDTO tag) {
		Tag entity = tagConversion.TagUpdVOToTag(tag);
		this.updateById(entity);
		Tag byId = this.getById(tag.getId());
		updTag(byId);
	}

	private List<Tag> getTagIsId(String id) {
		return selectTags().stream().filter(item->{
				if(item.getId().equals(id)){
					return true;
				}
				return false;
			}).collect(Collectors.toList());
	}

	//根据分类ID增加redis中指定分类的点击量
	private void addClickTag(String id){
		List<Tag> blogCategories = selectTags();
		List<Tag> collect = blogCategories.stream().map(item -> {
			if (item.getId().equals(id)) {
				item.setClickCount(item.getClickCount() + 1);
			}
			return item;
		}).collect(Collectors.toList());
		redisUtil.set(CacheNames.HOME_PAGE_TAGS, JSON.toJSON(collect));
	}
	//传入的对象增加redis
	private void addTag(Tag tag){
		List<Tag> blogCategories = selectTags();
		blogCategories.add(tag);
		redisUtil.set(CacheNames.HOME_PAGE_TAGS, JSON.toJSON(blogCategories));
	}
	//根据name从redis查找
	private List<Tag> getTagIsName(String tagName) {
		List<Tag> tags = selectTags().stream().filter(item -> {
			if (tagName.equals(item.getContent())) {
				return true;
			}
			return false;
		}).collect(Collectors.toList());
		return tags;
	}

	//修改数据redis
	private void updTag(Tag tag){
		List<Tag> tags = selectTags();
		List<Tag> collect = tags.stream().map(item -> {
			if (item.getId().equals(tag.getId())) {
				return tag;
			}
			return item;
		}).collect(Collectors.toList());
		redisUtil.set(CacheNames.HOME_PAGE_TAGS, JSON.toJSON(collect));
	}
}
